Claude Code 解读 01:Agent 架构设计与核心机制

来源说明:本文档译自 Claude Code 开源代码架构分析,原文为英文技术架构说明,本文进行完整中文解读与结构化重组。


一、经典 Agent Loop

Agent(智能体)的核心是一个循环运行的系统,它不断接收输入、思考、规划、执行,直到任务完成。一个典型的 Agent 架构如下:

用户输入 → 思考 → 规划 → 工具调用 → 执行结果
                              ↓
                     [继续循环]  或  [输出给用户]

这个循环的精妙之处在于:Agent 不需要预先知道所有步骤,而是通过"思考+执行+反馈"逐步完成任务。


二、Claude Code 的 Agent 实现

Claude Code 采用了分层架构,从用户界面到 API 调用共有四层:

┌─────────────────────────────────────────────────────────┐
│                    REPL.tsx                            │
│                   (用户界面层)                          │
│  • 捕获用户输入                                         │
│  • 渲染消息和工具结果                                    │
│  • 管理键盘快捷键                                       │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│                   QueryEngine                          │
│                  (会话管理层)                          │
│  • 管理多轮对话状态(mutableMessages)                   │
│  • 处理用户输入(submitMessage)                        │
│  • 整合系统提示词(fetchSystemPromptParts)             │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│              query() — 核心循环                         │
│          (Async Generator,流式处理)                  │
│                                                         │
│   while (true) {                                        │
│     [THINK]  → 构建请求,调用 API,处理 thinking 块      │
│     [PLAN]   → 解析 tool_use,执行工具                  │
│     [OUTPUT] → yield 消息事件,检查是否继续              │
│   }                                                     │
└─────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────┐
│            services/api/claude.ts                       │
│                   (API 适配层)                        │
│  • Anthropic SDK / Bedrock / Vertex / Azure            │
│  • 流式响应处理                                         │
└─────────────────────────────────────────────────────────┘

2.1 分层设计的核心逻辑

层级 模块 职责 生命周期
用户界面 REPL.tsx 捕获输入,渲染输出 长
会话管理 QueryEngine 管理多轮对话状态、权限 长
核心循环 query() 处理单个 API 请求/响应,执行工具 短(每轮对话可能调用多次)
API 适配 claude.ts 对接各大 AI 服务商 长

为什么这样拆分? - QueryEngine 是"长寿命"的,管理整个会话的生命周期 - query() 是"短寿命"的,每轮对话可能多次调用它来处理复杂任务


三、Async Generator:边想边说的艺术

3.1 传统方式 vs 流式方式

传统方式(等所有结果):

用户 → [等待 AI 完全思考完] → [等待所有工具执行完] → 返回结果
       ↑漫长的等待,用户以为卡死了

流式方式(实时响应):

用户 → yield thinking... → yield "我将执行 ls..."
                    → yield 工具结果...
                    → yield "完成了!"
       ↑ 用户实时看到 AI 的思考和行动

Claude Code 使用 JavaScript 的 Async Generator(异步生成器)实现真正的流式响应。query() 不是等所有结果都计算完再返回,而是每产出一个中间结果就 yield 出去,上层界面实时渲染给用户。

这解决了 Agent 应用的一个核心体验问题:用户不知道 AI 在干什么,以为它卡死了。

3.2 循环退出条件

while (true) {
  // THINK → PLAN → TOOL → OUTPUT
  const result = yield messageEvent;

  if (!result.needsFollowUp) {
    return; // 完成,退出循环
  }
  // 否则继续循环
}

当 AI 认为不需要继续执行工具时,循环结束,结果返回给用户。


四、工具系统设计

4.1 工具注册与定义

┌───────────────────────────────────────┐
│         Tool Registry                 │
│         tools.ts                      │
│                                       │
│  • BashTool / GlobTool / GrepTool   │
│  • FileEditTool / AgentTool          │
│  • ... 共 30+ 种工具                  │
└───────────────────────────────────────┘
                  │
                  ▼
┌───────────────────────────────────────┐
│         Tool Interface                │
│         src/Tool.ts                  │
│                                       │
│  name: string                        │
│  inputSchema: Zod                    │
│  call(): Promise<ToolResult>         │
│  renderResult(): ReactNode           │
└───────────────────────────────────────┘

每种工具都有: - name:工具名称 - inputSchema:用 Zod 定义的输入校验 - call():实际执行逻辑 - renderResult():在界面上渲染结果

4.2 流式工具执行器

┌─────────────────────────────────────────────────────┐
│            StreamingToolExecutor                     │
│              (流式工具执行器)                        │
│                                                     │
│  传统方式:所有工具串行执行完再返回                    │
│  流式方式:工具开始就 yield 结果,实时显示给用户       │
└─────────────────────────────────────────────────────┘

StreamingToolExecutor 允许工具边执行边 yield 结果,长时工具(如代码编译、大规模搜索)不会阻塞整个系统。


五、上下文管理:自动压缩机制

当对话越来越长,token 数量会逼近上下文窗口上限。Claude Code 的解决方案是自动上下文压缩:

messages[] ────────────────────────────────────────────
│                                                            
│  [用户消息1] [助手回复1] [工具结果1] [助手回复2] ...   
│                                                            
│                        │                                 
│                        ▼                                 
│              当上下文过长时...                          
│                        │                                 
│                        ▼                                 
│  ┌──────────────────────────────────────────────────┐  
│  │              AUTO COMPACT                         │  
│  │                                                  │  
│  │  [用户消息1] [助手回复1] [工具结果1] [助手回复2]  │  
│  │          ↓                                        │  
│  │  [用户消息1] [助手回复1] [ COMPACT_SUMMARY ]     │  
│  │           └────── 用摘要替换旧消息 ───────┘       │  
│  │                                                  │  
│  │  继续对话,但 token 数量减少了                     │  
│  └──────────────────────────────────────────────────┘  
└───────────────────────────────────────────────────────  

旧的多轮对话被压缩成一个 COMPACT_SUMMARY 块,保留关键信息的同时大幅减少 token 消耗。这使得超长对话成为可能,用户可以持续和 AI 协作数小时甚至数天。


六、与标准 Agent 架构对比

组件 标准 Agent Claude Code
输入 User/Task submitMessage()
思考 LLM 推理 API response(thinking blocks)
规划 Tool selection tool_use blocks + runTools()
执行 Tool execution StreamingToolExecutor
输出 Final response yield 实时流式响应
记忆 Memory/History mutableMessages[] + compact
循环 While not done while(true) + continue

七、核心执行流程

用户输入 "/buddy"
         │
         ▼
REPL.tsx 捕获输入
         │
         ▼
QueryEngine.submitMessage()
         │
   ┌─────┴──────┐
   │            │
   ▼            ▼
fetchSystemPromptParts()  processUserInput()
   │(构建系统提示词)   (处理slash命令)
   │
   ▼
query() AsyncGenerator
   │
   ├─► deps.callModel()          ← 调用 AI API(流式)
   │      │
   │      ├─► yield 'thinking...'     (如果有思考块)
   │      │
   │      ├─► yield 'text_delta...'  (实时文本)
   │      │
   │      └─► yield 'tool_use...'     (工具调用请求)
   │
   ├─► streamingToolExecutor      ← 流式执行工具
   │      │
   │      └─► yield tool results     (实时工具结果)
   │
   ├─► 检查 needsFollowUp
   │      │
   │      ├─► true:  continue  ← 继续循环
   │      │
   │      └─► false: return     ← 完成
   │
   ▼
REPL.tsx 渲染结果
         │
         ▼
用户看到实时响应

八、设计亮点总结

  1. Async Generator 实现真正的流式响应
  2. 用户不需要等待整个思考过程结束
  3. 可以实时看到 AI 的推理和行动,不会以为它卡死了

  4. 分离 QueryEngine 和 query()

  5. QueryEngine 管理会话生命周期(长寿命)
  6. query() 处理单轮对话逻辑(短寿命)

  7. 流式工具执行

  8. 工具结果可以边执行边显示
  9. 长时工具不会阻塞用户界面

  10. 自动上下文压缩

  11. 对话过长时自动压缩
  12. 可以持续超长对话而不会超出上下文限制

九、源码索引

模块 文件路径 职责
入口 src/entrypoints/cli.tsx CLI 入口,命令路由
主程序 src/main.tsx 初始化,REPL 启动
会话管理 src/QueryEngine.ts 多轮对话状态管理
核心循环 src/query.ts Async Generator 实现
API 层 src/services/api/claude.ts Anthropic API 封装
工具注册 src/tools.ts 工具列表管理
工具定义 src/tools/<Name>/ 各工具实现
状态管理 src/state/AppState.tsx React 状态
REPL UI src/screens/REPL.tsx 交互界面

十、读后感

Claude Code 的架构设计体现了几个重要的工程原则:

对于想构建自己 Agent 系统的人来说,Claude Code 的源码是一个非常好的参考样本——它足够简单(不是那种上千人的巨型项目),又足够完整(覆盖了 Agent 的所有核心要素)。


本文档为 Claude Code 开源代码的架构解读,原始分析来自 agent-architecture.md。